package com.openNetty.common.system;

import org.apache.commons.lang.StringUtils;

import java.io.*;
import java.net.URL;
import java.net.URLDecoder;
import java.util.Properties;

/**
 * @author zhenggm
 * @create 2017-11-20 下午 4:29
 **/


public class ConfigIOUtil {
    private static final String CONFIG = "config";

    /**
     * 获取配置文件的输入流.查找顺序为:jar包根目录同级config目录下,jar包根目录下config目录下,
     * jar包根目录下,jar包内根目录
     *
     * @param fileName 配置文件名称
     * @return 配置文件输入流, 获取失败返回NULL
     */
    public static InputStream getInputStream(String fileName) {
        return getInputStream(fileName, ConfigIOUtil.class);
    }

    /**
     * 获取配置文件的输入流.查找顺序为:jar包根目录同级config目录下,jar包根目录下config目录下,
     * jar包根目录下,jar包内根目录
     *
     * @param fileName  配置文件名称
     * @param codeClass jar包中的类对象
     * @return 配置文件输入流, 获取失败返回NULL
     */
    public static InputStream getInputStream(String fileName, Class<?> codeClass) {
        if (StringUtils.isNotEmpty(fileName)) {
            //文件在jar包外
            String path = null;
            try {
                path = filePath(fileName, codeClass);
            } catch (IOException e) {
                e.printStackTrace();
            }
            if (StringUtils.isNotEmpty(path)) {
                try {
                    return new FileInputStream(path);
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                }
            } else {//文件在jar包内
                try {
                    InputStream in = codeClass.getResourceAsStream(fileName);
                    if (in != null) {
                        return in;
                    } else {
                        return codeClass.getResourceAsStream("/" + fileName);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }

    /**
     * 获取配置文件的输出流.查找顺序为:jar包根目录同级config目录下,jar包根目录下config目录下,
     * jar包根目录下
     *
     * @param fileName 配置文件名称
     * @return 配置文件输出流, 获取失败返回NULL
     */
    public static OutputStream getOutputStream(String fileName) {
        return getOutputStream(fileName, ConfigIOUtil.class);
    }

    /**
     * 获取配置文件的输出流.查找顺序为:jar包根目录同级config目录下,jar包根目录下config目录下,
     * jar包根目录下
     *
     * @param fileName  配置文件名称
     * @param codeClass jar包中的类对象
     * @return 配置文件输出流, 获取失败返回NULL
     */
    public static OutputStream getOutputStream(String fileName, Class<?> codeClass) {
        try {
            String path = filePath(fileName, codeClass);
            if (StringUtils.isNotEmpty(path)) {
                return new FileOutputStream(path);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获取配置文件的文件对象.查找顺序为:jar包根目录同级config目录下,jar包根目录下config目录下,
     * jar包根目录下
     *
     * @param fileName 配置文件名称
     * @return 配置文件的文件对象, 获取失败返回NULL
     */
    public static File getFile(String fileName) {
        return getFile(fileName, ConfigIOUtil.class);
    }

    /**
     * 获取配置文件的文件对象.查找顺序为:jar包根目录同级config目录下,jar包根目录下config目录下,
     * jar包根目录下
     *
     * @param fileName  配置文件名称
     * @param codeClass jar包中的类对象
     * @return 配置文件的文件对象, 获取失败返回NULL
     */
    public static File getFile(String fileName, Class<?> codeClass) {
        try {
            String path = filePath(fileName, codeClass);
            if (StringUtils.isNotEmpty(path)) {
                return new File(path);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获取配置文件的绝对路径.查找顺序为:jar包根目录同级config目录下,jar包根目录下config目录下,
     * jar包根目录下
     *
     * @param fileName 配置文件名称
     * @return 配置文件的绝对路径, 获取失败返回NULL
     */
    public static String filePath(String fileName) throws IOException {
        return filePath(fileName, ConfigIOUtil.class);
    }

    /**
     * 获取配置文件的绝对路径.查找顺序为:jar包根目录同级config目录下,jar包根目录下config目录下,
     * jar包根目录下
     *
     * @param fileName  配置文件名称
     * @param codeClass jar包中的类对象
     * @return 配置文件的绝对路径, 获取失败返回NULL
     */
    public static String filePath(String fileName, Class<?> codeClass) throws IOException {
        if (StringUtils.isNotEmpty(fileName)) {
            File file = new File(fileName);
            if (file.exists()) {
                return fileName;
            }

            URL url = codeClass.getProtectionDomain().getCodeSource().getLocation();
            String path = null;
            try {
                path = URLDecoder.decode(url.getPath(), "UTF-8");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            if (path == null) {
                return null;
            }

            file = new File(path);
            file = file.getParentFile();//jar包根目录
            File config = new File(file.getParentFile(), CONFIG);
            // jar包根目录(bin)的同级config目录
            if (config.exists() && config.isDirectory()) {
                config = new File(config, fileName);
                if (config.exists()) {
                    return config.getCanonicalPath();
                }
            }
            // jar的同级config目录
            config = new File(file, CONFIG);
            if (config.exists() && config.isDirectory()) {
                config = new File(config, fileName);
                if (config.exists()) {
                    return config.getCanonicalPath();
                }
            }
            // jar的同级文件
            config = new File(file, fileName);
            if (config.exists()) {
                return config.getCanonicalPath();
            } else {
                return null;
            }
        }
        return null;
    }

    /**
     * 读取资源文件.查找顺序为:jar包根目录同级config目录下,jar包根目录下config目录下,
     * jar包根目录下,jar包内根目录
     *
     * @param fileName 配置文件名称
     * @return 资源文件对象, 获取失败返回NULL
     */
    public static Properties readResource(String fileName) {
        Properties properties = new Properties();
        if (StringUtils.isNotEmpty(fileName)) {
            InputStream in = null;
            try {
                in = ConfigIOUtil.getInputStream(fileName);
                if (in != null) {
                    properties.load(in);
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (in != null) {
                    try {
                        in.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        return properties;
    }
}
